{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "3434b662",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "**修改部分**：\n",
    "- 为每个代码单元添加中文注释概览；\n",
    "- 为缺少 docstring 的函数插入简要 docstring 模板；\n",
    "- 为常见 import 添加一行简短中文注释；\n",
    "- 对 pd.read_csv 补充 low_memory=False，规范 plt.show()，修正明显注释不一致；\n",
    "  "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "72ceeec7",
   "metadata": {},
   "source": [
    "# 描述性统计 Statistical Summary"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8c6ea7db",
   "metadata": {},
   "source": [
    "* 这项工作主要是让我们知道数据的整体状况怎么样，描述这个数据的“样子”。\n",
    "* 数据处理的最关键，也是最重要的第一步\n",
    "* 了解数据的概况，有助于后续的数据分析和挖掘"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0c79df6a",
   "metadata": {},
   "source": [
    "**描述性统计的Python工具**\n",
    "> PANDAS\n",
    "\n",
    "> NumPy和SciPy\n",
    "* count 统计非NA的数量\n",
    "* describe 针对series或者DF的列计算汇总统计\n",
    "* min max 最小值和最大值\n",
    "* quantile 样本分位数\n",
    "* sum 求和\n",
    "* mean 均值\n",
    "* median 中位数\n",
    "* mad 根据均值计算平均绝对离差\n",
    "* var 方差\n",
    "* std 标准差\n",
    "* skew 偏度（三阶矩）\n",
    "* kurt 峰度\n",
    "* cumsum 累计和\n",
    "* cumprod 累计乘积\n",
    "* diff 一阶差分\n",
    "* pct_change 计算百分数变化\n",
    "* mode 计算众数\n",
    "* cov 协方差\n",
    "* corrcoef 相关系数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "68def8da",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 1: 导入依赖库、绘图/可视化 ===\n",
    "import numpy as np # 数据处理最重要的模块\n",
    "import pandas as pd # 数据处理最重要的模块\n",
    "import scipy.stats as stats # 统计模块\n",
    "import scipy\n",
    "\n",
    "from datetime import datetime # 时间模块\n",
    "import statsmodels.formula.api as smf  # OLS regression\n",
    "\n",
    "from matplotlib import style  # 绘图\n",
    "import matplotlib.pyplot as plt  # 画图模块\n",
    "import matplotlib.dates as mdates  # 绘图\n",
    "\n",
    "from matplotlib.font_manager import FontProperties # 作图中文\n",
    "from pylab import mpl\n",
    "#mpl.rcParams['font.sans-serif'] = ['SimHei']\n",
    "#plt.rcParams['font.family'] = 'Times New Roman'\n",
    "\n",
    "#输出矢量图 渲染矢量图\n",
    "%matplotlib inline\n",
    "%config InlineBackend.figure_format = 'svg'\n",
    "\n",
    "from IPython.core.interactiveshell import InteractiveShell # jupyter运行输出的模块\n",
    "#显示每一个运行结果\n",
    "InteractiveShell.ast_node_interactivity = 'all'\n",
    "\n",
    "#设置行不限制数量\n",
    "#pd.set_option('display.max_rows',None)\n",
    "\n",
    "#设置列不限制数量\n",
    "pd.set_option('display.max_columns', None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c3ca85a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 2: 读取数据、数据清洗/转换 ===\n",
    "data = pd.read_csv('datasets/000001.csv', low_memory=False)\n",
    "data['Day'] = pd.to_datetime(data['Day'],format='%Y/%m/%d')\n",
    "data.set_index('Day', inplace = True)\n",
    "data.sort_values(by = ['Day'], ascending=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d7d93fe3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 3: 通用计算/执行 ===\n",
    "data_new = data['1995-01':'2025-08'].copy()\n",
    "data_new['Close'] = pd.to_numeric(data_new['Close'])\n",
    "data_new['Preclose'] = pd.to_numeric(data_new['Preclose'])\n",
    "# 计算000001上证指数日收益率 两种：\n",
    "data_new['Raw_return'] = data_new['Close'] / data_new['Preclose'] - 1\n",
    "data_new"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c24dbfa0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 4: 通用计算/执行 ===\n",
    "Month_data = data_new.resample('ME')['Raw_return'].apply(lambda x: (1+x).prod()-1).to_frame(name = 'Ret')\n",
    "Month_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "183ee0e8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 5: 通用计算/执行 ===\n",
    "Month_data = data_new.resample('ME')['Raw_return'].apply(lambda x: np.prod(1+x)-1).to_frame(name = 'Ret')\n",
    "Month_data.index.name = 'month'\n",
    "Month_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bc5c6074",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 6: 通用计算/执行 ===\n",
    "Quarter_data = data_new.resample('QE')['Raw_return'].apply(lambda x: np.prod(1+x)-1).to_frame(name = 'Ret')\n",
    "Quarter_data.index.name = 'Q'\n",
    "Quarter_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ca4cf4df",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 7: 通用计算/执行 ===\n",
    "Year_data = data_new.resample('YE')['Raw_return'].apply(lambda x: np.prod(1+x)-1).to_frame(name = 'Ret')\n",
    "Year_data.index.name = 'Y'\n",
    "Year_data"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7c40be61",
   "metadata": {},
   "source": [
    "# 收益率常见的描述性统计指标\n",
    "\n",
    " 在金融市场中，我们常用描述性统计指标来快速刻画收益率序列的分布特征，并可用数学公式进行精确定义：\n",
    " - **样本数（Count）**：表明可用观测值的多少，样本越充分统计结果越稳健。\n",
    "   - 公式：$n = \\text{len}(r_1, r_2, ..., r_n)$\n",
    " - **均值（Mean）**：衡量收益率的中心位置。\n",
    "   - 公式：$\\mu = \\frac{1}{n} \\sum_{i=1}^n r_i$\n",
    " - **中位数（Median）**：将所有收益率从小到大排列后处于中间的值。\n",
    " - **标准差（Standard Deviation）**：刻画收益波动的强弱，是风险度量的基础。\n",
    "   - 公式：$\\sigma = \\sqrt{\\frac{1}{n-1} \\sum_{i=1}^n (r_i - \\mu)^2}$\n",
    " - **方差（Variance）**：标准差的平方，反映波动的离散程度。\n",
    "   - 公式：$s^2 = \\frac{1}{n-1} \\sum_{i=1}^n (r_i - \\mu)^2$\n",
    " - **分位数（Quantiles）**：如25%、50%、75%分位数，可帮助我们了解收益率在不同位置的取值及尾部风险。\n",
    "   - 公式：$q_p = \\text{第} \\lceil np \\rceil \\text{小的数}$，$p$为分位点（如0.25, 0.5, 0.75）\n",
    " - **最小值与最大值（Min/Max）**：展示历史上出现过的极端收益。\n",
    "   - 公式：$\\min(r_1, ..., r_n)$，$\\max(r_1, ..., r_n)$\n",
    " - **正收益比例（% Positive）**：统计收益率为正的比例，直观反映赚钱的频率。\n",
    "   - 公式：$\\text{正收益比例} = \\frac{1}{n} \\sum_{i=1}^n I(r_i > 0)$，其中$I(\\cdot)$为指示函数\n",
    " - **偏度（Skewness）**：描述分布的不对称性，判断分布是否偏斜。\n",
    "   - 公式：$\\text{Skewness} = \\frac{1}{n} \\sum_{i=1}^n \\left(\\frac{r_i - \\mu}{\\sigma}\\right)^3$\n",
    " - **峰度（Kurtosis）**：描述分布的尖峭程度，判断是否存在肥尾或极端事件风险。\n",
    "   - 公式：$\\text{Kurtosis} = \\frac{1}{n} \\sum_{i=1}^n \\left(\\frac{r_i - \\mu}{\\sigma}\\right)^4$\n",
    " \n",
    "这些指标结合使用，就能为后续的风险控制、资产配置和策略研究提供扎实的“背景信息”。 -->"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a20ebb5d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 8: 数据清洗/转换、函数定义、循环/迭代 ===\n",
    "# 汇总日/月/年收益率的描述性统计指标\n",
    "def summarize_returns(series):\n",
    "    \"\"\"\n",
    "    功能：请简述函数 summarize_returns 的目的和作用。\n",
    "    参数：\n",
    "    - series: 参数说明\n",
    "    返回：请描述返回值的含义与类型。\n",
    "    \"\"\"\n",
    "    clean_series = series.dropna()\n",
    "    return pd.Series({\n",
    "        '样本数': clean_series.count(),\n",
    "        '均值': clean_series.mean(),\n",
    "        '中位数': clean_series.median(),\n",
    "        '标准差': clean_series.std(),\n",
    "        '方差': clean_series.var(),\n",
    "        '最小值': clean_series.min(),\n",
    "        '25%分位数': clean_series.quantile(0.25),\n",
    "        '50%分位数': clean_series.quantile(0.5),\n",
    "        '75%分位数': clean_series.quantile(0.75),\n",
    "        '最大值': clean_series.max(),\n",
    "        '正收益比例': (clean_series > 0).mean(),\n",
    "        '偏度': clean_series.skew(),\n",
    "        '峰度': clean_series.kurt()\n",
    "    })\n",
    "\n",
    "return_periods = {\n",
    "    '日收益率': data_new.loc['2000-01':'2025-08', 'Raw_return'],\n",
    "    '月收益率': Month_data.loc['2000-01':'2025-08', 'Ret'],\n",
    "    '年收益率': Year_data.loc['2000':'2025', 'Ret']\n",
    "}\n",
    "\n",
    "returns_summary = pd.DataFrame({\n",
    "    name: summarize_returns(series) for name, series in return_periods.items()\n",
    "}).T\n",
    "returns_summary['正收益比例'] = returns_summary['正收益比例'].mul(100)\n",
    "returns_summary.rename(columns={'正收益比例': '正收益比例(%)'}, inplace=True)\n",
    "returns_summary = returns_summary.round({\n",
    "    '样本数': 0,\n",
    "    '均值': 5,\n",
    "    '中位数': 5,\n",
    "    '标准差': 5,\n",
    "    '方差': 7,\n",
    "    '最小值': 5,\n",
    "    '25%分位数': 5,\n",
    "    '50%分位数': 5,\n",
    "    '75%分位数': 5,\n",
    "    '最大值': 5,\n",
    "    '正收益比例(%)': 2,\n",
    "    '偏度': 3,\n",
    "    '峰度': 3\n",
    "})\n",
    "returns_summary['样本数'] = returns_summary['样本数'].astype(int)\n",
    "returns_summary"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1bc2f4d3",
   "metadata": {},
   "source": [
    "## 均值 mean"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "18b48d53",
   "metadata": {},
   "source": [
    "算数平均：\n",
    "$$A_n=\\frac{a_1+a_2+a_3+\\cdots+a_n}{n}$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8d4dac5b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 9: 通用计算/执行 ===\n",
    "round(data_new['2000-01':'2024-09']['Raw_return'].mean(),5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "89422eb5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 10: 通用计算/执行 ===\n",
    "#注意以下代码的书写逻辑，和上面的代码不同\n",
    "np.mean(data_new['2000-01':'2024-09']['Raw_return'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bd132504",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 11: 通用计算/执行 ===\n",
    "print('中国股票市场日度平均收益率为',data_new['2000-01':'2025-08']['Raw_return'].mean().round(5)*100,'%',sep=\"\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "58c3cbea",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 12: 通用计算/执行 ===\n",
    "print('中国股票市场月度平均收益率为',Month_data['2000-01':'2025-08']['Ret'].mean().round(3)*100,'%',sep=\"\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d265f5e1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 13: 通用计算/执行 ===\n",
    "print('中国股票市场年度平均收益率为',Year_data['2000':'2025']['Ret'].mean().round(5)*100,'%',sep=\"\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4278af7c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 14: 通用计算/执行 ===\n",
    "sum(data_new['2000-01':'2024-09']['Raw_return']) / len(data_new['2000-01':'2024-09']['Raw_return'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0819d3d5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 15: 通用计算/执行 ===\n",
    "data_new['1995-01':'2024-09']['Raw_return'].describe()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8573078c",
   "metadata": {},
   "source": [
    "# 分位数 quantile"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "82451dc5",
   "metadata": {},
   "source": [
    "分位数（Quantile），亦称分位点，是指将一个随机变量的概率分布范围分为几个等份的数值点，常用的有中位数（即二分位数）、四分位数、百分位数等。\n",
    "\n",
    "举例说明，我们班上有10名同学，他们的期末成绩是\n",
    "\n",
    "【20，24，38，34，43，56，76，86，98，100】\n",
    "\n",
    "如果期末考试要让40%的不通过，60%的人通过，分数线是多少呢？"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3080778f",
   "metadata": {},
   "source": [
    "常见的分类方法：\n",
    "\n",
    "- 中位数 Median\n",
    "  - 当N是奇数时\n",
    "    - $$m_{0.5}=X_{(N+1) / 2}$$\n",
    "  - 当N是偶数时\n",
    "    - $$m_{0.5}=\\frac{X_{(N / 2)}+X_{(N / 2+1)}}{2}$$\n",
    "- 四分位数 Quartile\n",
    "- 10分位数 常用在股票投资策略中"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b54d9b9",
   "metadata": {},
   "source": [
    "Some q-quantiles have special names:\n",
    "\n",
    "- The only 2-quantile is called the median\n",
    "- The 3-quantiles are called tertiles or terciles \n",
    "- The 4-quantiles are called quartiles \n",
    "- The 5-quantiles are called quintiles \n",
    "- The 6-quantiles are called sextiles \n",
    "- The 7-quantiles are called septiles\n",
    "- The 8-quantiles are called octiles\n",
    "- The 10-quantiles are called deciles\n",
    "- The 12-quantiles are called duo-deciles or dodeciles\n",
    "- The 16-quantiles are called hexadeciles\n",
    "- The 20-quantiles are called ventiles, vigintiles, or demi-deciles \n",
    "- The 100-quantiles are called percentiles"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "96fb6a32",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 16: 通用计算/执行 ===\n",
    "len(data_new['1995-01':'2024-09'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9a20472c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 17: 通用计算/执行 ===\n",
    "len(data_new[data_new[\"Raw_return\"] > 0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f5a33bd6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 18: 通用计算/执行 ===\n",
    "len(data_new[data_new[\"Raw_return\"] > 0])/len(data_new)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4659270a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 19: 导入依赖库 ===\n",
    "from statistics import quantiles\n",
    "\n",
    "# quantiles函数里面的参数需要注意\n",
    "# 计算data_new在1995-01到2025-08期间Raw_return的十分位数\n",
    "# n=10 表示分成10份（十分位数），method='exclusive' 表示使用不包含端点的分位数计算方法\n",
    "quantiles(data_new['1995-01':'2025-08']['Raw_return'], n = 10, method='exclusive')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "540ab9ed",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 20: 通用计算/执行 ===\n",
    "quantiles(data_new['1995-01':'2024-09']['Raw_return'], n = 10, method='inclusive') # 在金融里，比如构造分位数组合（5分位、10分位），常用的还是 inclusive（更贴近排序分组）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b94d9553",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 21: 导入依赖库 ===\n",
    "import statistics\n",
    "help(statistics.quantiles)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41625b6d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 22: 通用计算/执行 ===\n",
    "data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n",
    "q = statistics.quantiles(data, n=4, method='exclusive')\n",
    "print(q)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fa472f54",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 23: 通用计算/执行 ===\n",
    "q = statistics.quantiles(data, n=4, method='inclusive')\n",
    "print(q)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "69b0a933",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 24: 通用计算/执行 ===\n",
    "Month_data['2000-01':'2025-08']['Ret'].describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bc67bad4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 25: 通用计算/执行 ===\n",
    "statistics.quantiles(Month_data['Ret'], n = 10, method='inclusive')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "773cea88",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 26: 通用计算/执行 ===\n",
    "len(Month_data['1995-01':'2024-09'][Month_data[\"Ret\"] > 0])/len(Month_data['1995-01':'2025-08'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "237b40a2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 27: 通用计算/执行 ===\n",
    "quantiles(Month_data['2000-01':'2025-08']['Ret'], n = 10, method='exclusive')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "de9d91b7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 28: 通用计算/执行 ===\n",
    "seq = np.linspace(0,1,11)\n",
    "seq"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7309878e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 29: 通用计算/执行 ===\n",
    "np.quantile(data_new['2000-01':'2024-09']['Raw_return'],q=seq)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b90a8752",
   "metadata": {},
   "source": [
    "# 波动率 Variance"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e64e2ec",
   "metadata": {},
   "source": [
    "$$\\sigma^2=\\frac{\\sum(X-\\mu)^2}{N}$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6c50a3be",
   "metadata": {},
   "source": [
    "$$ R_{t+1} = a + b * VAR_t $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6ea0a7a6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 30: 通用计算/执行 ===\n",
    "np.var(data_new['2000-01':'2025-08']['Raw_return'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "aaa35f77",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 31: 通用计算/执行 ===\n",
    "m = np.mean(data_new['2000-01':'2025-08']['Raw_return'])\n",
    "sum((data_new['2000-01':'2025-08']['Raw_return'] - m)**2) / len(data_new['2000-01':'2025-08']['Raw_return'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "865980e1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 32: 通用计算/执行 ===\n",
    "np.std(data_new['2000-01':'2025-08']['Raw_return'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cd7e817f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 33: 通用计算/执行 ===\n",
    "np.sqrt(np.var(data_new['2000-01':'2025-08']['Raw_return']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0808d1ab",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 34: 导入依赖库 ===\n",
    "from math import sqrt  # 数学函数\n",
    "\n",
    "sqrt(np.var(data_new['2000-01':'2024-09']['Raw_return']))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2190bf1a",
   "metadata": {},
   "source": [
    "# 作业\n",
    "计算每个月的波动率，也就是方差。\n",
    "\n",
    "- resample\n",
    "- groupby"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fd4c5126",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 35: 通用计算/执行 ===\n",
    "monthly_var = data_new.resample('ME')['Raw_return'].var().to_frame(name = 'variance')\n",
    "monthly_var.index.name = 'month'\n",
    "monthly_var"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d852ca4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 36: 通用计算/执行 ===\n",
    "monthly_var = data_new.resample('ME')['Raw_return'].apply(lambda x: np.sum(x ** 2)).to_frame(name = 'variance')\n",
    "monthly_var.index.name = 'month'\n",
    "monthly_var"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e768773",
   "metadata": {},
   "source": [
    "# 正态分布（Normal Distribution）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "df574331",
   "metadata": {},
   "source": [
    "若随机变量X服从一个数学期望为 $\\mu$ 、方差为 $\\sigma^{2}$ 的正态分布，记为 $\\mathrm{N}\\left(\\mu, \\sigma^{2}\\right)$ 。其概率密度函数为正态分布的期望值决定了 其位置，其标准差$\\sigma$决定了分布的幅度。当 $\\mu=0, \\sigma=1$ 时的正态分布是标准正态分布。\n",
    "\n",
    "若随机变量 $X$ 服从一个位置参数为 $\\mu$ 、尺度参数为 $\\sigma$ 的概率分布，且其概率密度函数为 \n",
    "$$\n",
    "f(x)=\\frac{1}{\\sqrt{2 \\pi} \\sigma} \\exp \\left(-\\frac{(x-\\mu)^{2}}{2 \\sigma^{2}}\\right)\n",
    "$$\n",
    "则这个随机变量就称为正态随机变量, 正态随机变量服从的分布就称为正态分布, 记作 $X \\sim N\\left(\\mu, \\sigma^{2}\\right)$, 读作 $X$ 服从 $N\\left(\\mu, \\sigma^{2}\\right)$, 或 $X$ 服从正态分布。\n",
    "\n",
    " 若 $X \\sim N\\left(\\mu, \\sigma^{2}\\right), Y=\\frac{X-\\mu}{\\sigma} \\sim N(0,1)$.\n",
    " \n",
    " 当 $\\mu=0, \\sigma=1$ 时，正态分布就成为标准正态分布\n",
    "$$\n",
    "f(x)=\\frac{1}{\\sqrt{2 \\pi}} e^{\\left(-\\frac{x^{2}}{2}\\right)}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7f6b96a1",
   "metadata": {},
   "source": [
    "# 偏度和峰度"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76c82de2",
   "metadata": {},
   "source": [
    "* 偏度（Skewness）是统计数据分布偏斜方向和程度的度量，是统计数据分布非对称程度的数字特征。定义上偏度是样本的三阶标准化矩。\n",
    "$$\n",
    "S=\\frac{1}{n} \\sum_{i=1}^{n}\\left[\\left(\\frac{X_{i}-\\mu}{\\sigma}\\right)^{3}\\right]\n",
    "$$\n",
    "\n",
    "其中 $\\mu$ 是均值， $\\sigma$ 是标准差。定义中包括正态分布（偏度=0），右偏分布（正偏，>0）,左偏分布（负偏，<0）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cf8e565c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 37: 导入依赖库、绘图/可视化 ===\n",
    "# 导入所需库\n",
    "import numpy as np  # 数值计算\n",
    "import matplotlib.pyplot as plt  # 绘图\n",
    "from scipy.stats import skewnorm, skew\n",
    "import seaborn as sns  # 统计可视化\n",
    "\n",
    "# 设置中文字体，以正常显示图中的中文标签\n",
    "# 请确保您的环境中已安装'PingFang SC'字体（macOS默认），否则可以替换为其他中文字体\n",
    "try:\n",
    "    plt.rcParams['font.sans-serif'] = ['PingFang SC', 'Arial Unicode MS'] # macOS常用中文字体，并添加备用字体\n",
    "    plt.rcParams['axes.unicode_minus'] = False # 解决负号'-'显示为方块的问题\n",
    "except Exception as e:\n",
    "    print(f\"设置中文字体失败，请检查字体是否安装: {e}\")\n",
    "    # 如果没有'PingFang SC'字体，可以注释掉上面两行，或者更换为系统支持的其他中文字体\n",
    "\n",
    "# --- 1. 生成不同偏度的数据 ---\n",
    "np.random.seed(42) # 设置随机种子，保证每次运行结果一致\n",
    "n_samples = 5000   # 样本数量\n",
    "\n",
    "# 生成负偏度数据 (左偏)\n",
    "# a < 0 会产生负偏度\n",
    "data_neg = skewnorm.rvs(a=-5, loc=20, scale=5, size=n_samples)\n",
    "skew_neg = skew(data_neg)\n",
    "\n",
    "# 生成零偏度数据 (对称分布，接近正态分布)\n",
    "# a = 0 时，skewnorm生成的就是正态分布\n",
    "data_zero = skewnorm.rvs(a=0, loc=0, scale=5, size=n_samples)\n",
    "skew_zero = skew(data_zero)\n",
    "\n",
    "# 生成正偏度数据 (右偏)\n",
    "# a > 0 会产生正偏度\n",
    "data_pos = skewnorm.rvs(a=5, loc=-20, scale=5, size=n_samples)\n",
    "skew_pos = skew(data_pos)\n",
    "\n",
    "# --- 2. 可视化 ---\n",
    "# 创建一个1行3列的图，用于并排展示三个分布\n",
    "fig, axes = plt.subplots(3,1, figsize=(6, 9))\n",
    "fig.suptitle('偏度分布示例', fontsize=20)\n",
    "\n",
    "\n",
    "# (1) 绘制负偏度分布图\n",
    "sns.histplot(data_neg, kde=True, ax=axes[0], color='coral', bins=50)\n",
    "axes[0].set_title(f'负偏度 (左偏)\\n偏度值 ≈ {skew_neg:.2f}', fontsize=16)\n",
    "axes[0].set_xlabel('数值', fontsize=12)\n",
    "axes[0].set_ylabel('频数', fontsize=12)\n",
    "# 标出均值和中位数的位置，帮助理解偏度对它们的影响\n",
    "mean_neg = np.mean(data_neg)\n",
    "median_neg = np.median(data_neg)\n",
    "axes[0].axvline(mean_neg, color='red', linestyle='--', linewidth=2, label=f'均值: {mean_neg:.2f}')\n",
    "axes[0].axvline(median_neg, color='green', linestyle='-', linewidth=2, label=f'中位数: {median_neg:.2f}')\n",
    "axes[0].legend()\n",
    "axes[0].text(0.05, 0.9, '均值 < 中位数', transform=axes[0].transAxes, fontsize=12, color='blue')\n",
    "\n",
    "\n",
    "# (2) 绘制零偏度分布图\n",
    "sns.histplot(data_zero, kde=True, ax=axes[1], color='skyblue', bins=50)\n",
    "axes[1].set_title(f'零偏度 (对称)\\n偏度值 ≈ {skew_zero:.2f}', fontsize=16)\n",
    "axes[1].set_xlabel('数值', fontsize=12)\n",
    "axes[1].set_ylabel('') # 中间的图不显示y轴标签，避免拥挤\n",
    "mean_zero = np.mean(data_zero)\n",
    "median_zero = np.median(data_zero)\n",
    "axes[1].axvline(mean_zero, color='red', linestyle='--', linewidth=2, label=f'均值: {mean_zero:.2f}')\n",
    "axes[1].axvline(median_zero, color='green', linestyle='-', linewidth=2, label=f'中位数: {median_zero:.2f}')\n",
    "axes[1].legend()\n",
    "axes[1].text(0.05, 0.9, '均值 ≈ 中位数', transform=axes[1].transAxes, fontsize=12, color='blue')\n",
    "\n",
    "\n",
    "# (3) 绘制正偏度分布图\n",
    "sns.histplot(data_pos, kde=True, ax=axes[2], color='lightgreen', bins=50)\n",
    "axes[2].set_title(f'正偏度 (右偏)\\n偏度值 ≈ {skew_pos:.2f}', fontsize=16)\n",
    "axes[2].set_xlabel('数值', fontsize=12)\n",
    "axes[2].set_ylabel('')\n",
    "mean_pos = np.mean(data_pos)\n",
    "median_pos = np.median(data_pos)\n",
    "axes[2].axvline(mean_pos, color='red', linestyle='--', linewidth=2, label=f'均值: {mean_pos:.2f}')\n",
    "axes[2].axvline(median_pos, color='green', linestyle='-', linewidth=2, label=f'中位数: {median_pos:.2f}')\n",
    "axes[2].legend()\n",
    "axes[2].text(0.05, 0.9, '均值 > 中位数', transform=axes[2].transAxes, fontsize=12, color='blue')\n",
    "\n",
    "\n",
    "# 调整布局并显示图像\n",
    "plt.tight_layout(rect=[0, 0, 1, 0.95]) # 调整布局，为大标题留出空间\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84be8d6d",
   "metadata": {},
   "source": [
    "* 峰度（Kurtosis）表征概率密度分布曲线在平均值处峰度高低的特征。直观来看，峰度反应了峰部的尖度。其计算方法为\n",
    "   $$K=\\frac{1}{n} \\sum_{i=1}^{n}\\left[\\left(\\frac{X_{i}-\\mu}{\\sigma}\\right)^{4}\\right]$$\n",
    "    其中 $\\mu$ 是均值， $\\sigma$ 是标准差。定义中包括正态分布（峰度=3），厚尾（峰度>3）,瘦尾（峰度<3）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ae060d5a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 38: 导入依赖库、绘图/可视化 ===\n",
    "# 导入所需库\n",
    "import numpy as np  # 数值计算\n",
    "import matplotlib.pyplot as plt  # 绘图\n",
    "from scipy.stats import kurtosis, norm, laplace, uniform\n",
    "import seaborn as sns  # 统计可视化\n",
    "\n",
    "# 设置中文字体，以正常显示图中的中文标签\n",
    "# 请确保您的环境中已安装'PingFang SC'字体（macOS默认），否则可以替换为其他中文字体\n",
    "try:\n",
    "    plt.rcParams['font.sans-serif'] = ['PingFang SC', 'Arial Unicode MS'] # macOS常用中文字体，并添加备用字体\n",
    "    plt.rcParams['axes.unicode_minus'] = False # 解决负号'-'显示为方块的问题\n",
    "except Exception as e:\n",
    "    print(f\"设置中文字体失败，请检查字体是否安装: {e}\")\n",
    "    # 如果没有'PingFang SC'字体，可以注释掉上面两行，或者更换为系统支持的其他中文字体\n",
    "\n",
    "# --- 1. 生成不同峰度的数据 ---\n",
    "np.random.seed(42)\n",
    "n_samples = 10000\n",
    "\n",
    "# 生成尖峰/厚尾数据 (Leptokurtic)\n",
    "# 拉普拉斯分布是典型的尖峰厚尾分布\n",
    "data_lepto = laplace.rvs(loc=0, scale=1, size=n_samples)\n",
    "# 使用 fisher=False 计算原始峰度值，此时正态分布的峰度为3\n",
    "kurt_lepto = kurtosis(data_lepto, fisher=False)\n",
    "\n",
    "# 生成常态峰数据 (Mesokurtic)\n",
    "# 正态分布\n",
    "data_meso = norm.rvs(loc=0, scale=1.5, size=n_samples) # 调整scale使视觉效果更清晰\n",
    "kurt_meso = kurtosis(data_meso, fisher=False)\n",
    "\n",
    "# 生成低阔峰/瘦尾数据 (Platykurtic)\n",
    "# 均匀分布是典型的低阔峰\n",
    "data_platy = uniform.rvs(loc=-3, scale=6, size=n_samples) # 范围从-3到3\n",
    "kurt_platy = kurtosis(data_platy, fisher=False)\n",
    "\n",
    "# --- 2. 可视化 ---\n",
    "fig, axes = plt.subplots(3, 1, figsize=(6, 9))\n",
    "fig.suptitle('峰度分布示例', fontsize=20)\n",
    "common_xlim = (-6, 6) # 设置统一的x轴范围，便于比较\n",
    "\n",
    "# (1) 绘制尖峰/厚尾分布\n",
    "sns.histplot(data_lepto, kde=True, ax=axes[0], color='tomato', bins=50)\n",
    "axes[0].set_title(f'尖峰/厚尾 (Leptokurtic)\\n峰度值 ≈ {kurt_lepto:.2f} (> 3)', fontsize=16)\n",
    "axes[0].set_xlabel('数值', fontsize=12)\n",
    "axes[0].set_ylabel('频数', fontsize=12)\n",
    "axes[0].set_xlim(common_xlim)\n",
    "\n",
    "# (2) 绘制常态峰分布\n",
    "sns.histplot(data_meso, kde=True, ax=axes[1], color='skyblue', bins=50)\n",
    "axes[1].set_title(f'常态峰 (Mesokurtic)\\n峰度值 ≈ {kurt_meso:.2f} (≈ 3)', fontsize=16)\n",
    "axes[1].set_xlabel('数值', fontsize=12)\n",
    "axes[1].set_ylabel('')\n",
    "axes[1].set_xlim(common_xlim)\n",
    "\n",
    "# (3) 绘制低阔峰/瘦尾分布\n",
    "sns.histplot(data_platy, kde=True, ax=axes[2], color='lightgreen', bins=50)\n",
    "axes[2].set_title(f'低阔峰/瘦尾 (Platykurtic)\\n峰度值 ≈ {kurt_platy:.2f} (< 3)', fontsize=16)\n",
    "axes[2].set_xlabel('数值', fontsize=12)\n",
    "axes[2].set_ylabel('')\n",
    "axes[2].set_xlim(common_xlim)\n",
    "\n",
    "# 调整布局并显示图像\n",
    "plt.tight_layout(rect=[0, 0, 1, 0.95])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e6ead316",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 39: 通用计算/执行 ===\n",
    "# Daily data\n",
    "len(data_new['1995-01':'2025-08'])\n",
    "data_new['1995-01':'2025-08']['Raw_return'].skew()\n",
    "data_new['1995-01':'2025-08']['Raw_return'].kurt()\n",
    "scipy.stats.kurtosis(data_new['1995-01':'2025-08']['Raw_return'],fisher=False) - 3\n",
    "scipy.stats.kurtosis(data_new['1995-01':'2025-08']['Raw_return'],fisher=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13c77b40",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 40: 通用计算/执行 ===\n",
    "m = np.mean(data_new['1995-01':'2024-09']['Raw_return'])\n",
    "l = len(data_new['1995-01':'2024-09']['Raw_return'])\n",
    "sum(((data_new['1995-01':'2024-09']['Raw_return'] - m)/np.std(data_new['1995-01':'2024-09']['Raw_return']))**4) / l -3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a6301edc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 41: 通用计算/执行 ===\n",
    "# Monthly data\n",
    "Month_data['1995-01':'2024-09']['Ret'].skew()\n",
    "Month_data['1995-01':'2024-09']['Ret'].kurt()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a0862efb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 42: 通用计算/执行 ===\n",
    "# Quarterly data\n",
    "Quarter_data['1995-01':'2024-09']['Ret'].skew()\n",
    "Quarter_data['1995-01':'2024-09']['Ret'].kurt()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ce1b978c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 43: 通用计算/执行 ===\n",
    "Year_data['1995-01':'2024-09']['Raw_return'].skew()\n",
    "Year_data['1995-01':'2024-09']['Raw_return'].kurt()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c13ac28e",
   "metadata": {},
   "source": [
    "# 标准正态分布的直方图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ceb6af3b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 44: 绘图/可视化、函数定义 ===\n",
    "# 根据均值、标准差,求指定范围的正态分布概率值\n",
    "\n",
    "'''\"\n",
    "normfun(x, mu, sigma) 函数定义了一个正态分布的概率密度函数，\n",
    "其中 x 是自变量\n",
    "mu 是均值\n",
    "sigma 是标准差\n",
    "这个函数计算了在给定均值和标准差下 x 处的概率密度值。\n",
    "'''\n",
    "\n",
    "def normfun(x, mu, sigma):\n",
    "    \"\"\"\n",
    "    功能：请简述函数 normfun 的目的和作用。\n",
    "    参数：\n",
    "    - x: 参数说明\n",
    "    - mu: 参数说明\n",
    "    - sigma: 参数说明\n",
    "    返回：请描述返回值的含义与类型。\n",
    "    \"\"\"\n",
    "  pdf = np.exp(-((x - mu)**2)/(2*sigma**2)) / (sigma * np.sqrt(2*np.pi))\n",
    "  return pdf\n",
    "\n",
    "\n",
    "# 生成高斯分布的概率密度随机数\n",
    "result = np.random.normal(0, 1, 1000000) # mean 0 and standard deviation 1\n",
    "\n",
    "# np.arange()\n",
    "# 函数返回一个有终点和起点的固定步长的排列，如[1,2,3,4,5]，起点是1，终点是6，步长为1。\n",
    "# 参数个数情况： np.arange()函数分为一个参数，两个参数，三个参数三种情况\n",
    "# 1）一个参数时，参数值为终点，起点取默认值0，步长取默认值1。\n",
    "# 2）两个参数时，第一个参数为起点，第二个参数为终点，步长取默认值1。\n",
    "# 3）三个参数时，第一个参数为起点，第二个参数为终点，第三个参数为步长。其中步长支持小数\n",
    "\n",
    "x = np.arange(min(result), max(result),0.01)\n",
    "\n",
    "# 设定 y 轴，载入刚才的正态分布函数\n",
    "y = normfun(x, result.mean(), result.std())\n",
    "\n",
    "# 修改画图的大小\n",
    "plt.figure(figsize=(8, 4)) # 设置图形大小为宽10英寸，高6英寸\n",
    "plt.plot(x, y) # 这里画出理论的正态分布概率曲线\n",
    " \n",
    "# 这里画出实际的参数概率与取值关系\n",
    "fig = plt.hist(result, bins=100, rwidth=1, density=True) # bins=100 表示将数据分成100个柱状图，density=True 表示将频率转换为概率密度。宽度是rwidth(0~1),=1没有缝隙\n",
    "plt.title('distribution')\n",
    "#plt.xlabel('')\n",
    "plt.ylabel('probability')\n",
    "# 输出\n",
    "plt.show() # 最后图片的概率和不为1是因为正态分布是从负无穷到正无穷,这里指截取了数据最小值到最大值的分布"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bfd860c6",
   "metadata": {},
   "source": [
    "# 在日收益率直方图上添加正态分布密度曲线"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d67d6c1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 45: 绘图/可视化、函数定义 ===\n",
    "retmean = data_new['2000-01':'2025-08']['Raw_return'].mean()\n",
    "retstd = data_new['2000-01':'2025-08']['Raw_return'].std()\n",
    "retmin = data_new['2000-01':'2025-08']['Raw_return'].min()\n",
    "retmax = data_new['2000-01':'2025-08']['Raw_return'].max()\n",
    "\n",
    "\n",
    "def normfun(x, mu, sigma):\n",
    "    \"\"\"\n",
    "    功能：请简述函数 normfun 的目的和作用。\n",
    "    参数：\n",
    "    - x: 参数说明\n",
    "    - mu: 参数说明\n",
    "    - sigma: 参数说明\n",
    "    返回：请描述返回值的含义与类型。\n",
    "    \"\"\"\n",
    "    pdf = np.exp(-((x - mu)**2) /\n",
    "                 (2 * sigma**2)) / (sigma * np.sqrt(2 * np.pi))\n",
    "    return pdf\n",
    "\n",
    "\n",
    "x = np.arange(retmin, retmax, 0.001) # 0.001 0.002 0.003 0.004.。。。 0.099 0.100  0.101\n",
    "y = normfun(x, retmean, retstd)\n",
    "fig = plt.figure(figsize=(10, 5))\n",
    "plt.plot(x, y)\n",
    "\n",
    "fig = plt.hist(data_new['2000-01':'2025-08']['Raw_return'], # index daily market excess return\n",
    "               bins=1000,\n",
    "               histtype='bar',\n",
    "               color='r',\n",
    "               alpha=0.9)\n",
    "plt.xticks(rotation=90, fontsize=8) # x轴显示方法\n",
    "plt.title('Distribution')\n",
    "plt.xlabel('Market Return From January 2000 to Augest 2025')\n",
    "plt.ylabel('Probability')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2130fd5",
   "metadata": {},
   "source": [
    "# 在月收益率直方图上添加正态分布密"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9f902690",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 46: 绘图/可视化、函数定义 ===\n",
    "retmean = Month_data['2000-01':'2025-08']['Ret'].mean()\n",
    "retstd = Month_data['2000-01':'2025-08']['Ret'].std()\n",
    "retmin = Month_data['2000-01':'2025-08']['Ret'].min()\n",
    "retmax = Month_data['2000-01':'2025-08']['Ret'].max()\n",
    "\n",
    "\n",
    "def normfun(x, mu, sigma):\n",
    "    \"\"\"\n",
    "    功能：请简述函数 normfun 的目的和作用。\n",
    "    参数：\n",
    "    - x: 参数说明\n",
    "    - mu: 参数说明\n",
    "    - sigma: 参数说明\n",
    "    返回：请描述返回值的含义与类型。\n",
    "    \"\"\"\n",
    "    pdf = np.exp(-((x - mu)**2) /\n",
    "                 (2 * sigma**2)) / (sigma * np.sqrt(2 * np.pi))\n",
    "    return pdf\n",
    "\n",
    "\n",
    "x = np.arange(retmin, retmax, 0.001)\n",
    "y = normfun(x, retmean, retstd)\n",
    "fig = plt.figure(figsize=(10, 5)) # 图片大小 10，5\n",
    "plt.plot(x, y)\n",
    "\n",
    "fig = plt.hist(Month_data['2000-01':'2025-08']['Ret'],\n",
    "               bins=100,\n",
    "               histtype='bar',\n",
    "               color='r',\n",
    "               alpha=0.9)\n",
    "plt.xticks(rotation=90, fontsize=8)\n",
    "plt.title('Distribution')\n",
    "plt.xlabel('Market Return From January 2000 to December 2023')\n",
    "plt.ylabel('Probability')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7567d23a",
   "metadata": {},
   "source": [
    "# 平稳性 stationary\n",
    "\n",
    "\n",
    "### 什么是平稳性 (Stationarity)？\n",
    "\n",
    "想象一下，你正在观察一条河流。如果你在任何一天、任何一周、任何一年去观察，发现这条河的水位总是在一个相似的高度上下波动，水流的速度也维持在一个稳定的范围内，那么我们可以说这条河的状貌是“平稳”的。\n",
    "\n",
    "在时间序列分析中，“平稳性”就是类似的概念。一个时间序列如果具有平稳性，意味着它的统计特性不随时间的变化而变化。具体来说，我们通常关注的是**弱平稳性**（也叫协方差平稳性），它要求满足以下三个条件：\n",
    "\n",
    "1.  **均值恒定**：序列的均值（期望值）是一个常数，不随时间t的变化而改变。就像那条河，无论你在1月份还是7月份测量，它的平均水位都是相似的。\n",
    "2.  **方差恒定**：序列的方差是一个常数，不随时间t的变化而改变。这意味着序列的波动程度是稳定的。河水的波动幅度（浪花的大小）不会因为季节变化而发生系统性的剧烈改变。\n",
    "3.  **协方差只与时间间隔有关**：序列在任意两个时间点（t和t-k）的协方差，只取决于它们之间的时间间隔k，而与具体的时间点t无关。也就是说，今天和昨天的关联程度，与去年今天和去年昨天的关联程度是一样的。\n",
    "\n",
    "**一个非平稳的例子**：一支股票的价格。比如S&P 500指数，从1980年到今天，它的均值（平均价格水平）明显是不断上升的，这违背了“均值恒定”的原则，所以股价序列通常是非平稳的。\n",
    "\n",
    "### 什么是遍历性 (Ergodicity)？\n",
    "\n",
    "遍历性是一个更抽象，但同样重要的概念。它关系到我们如何利用有限的数据去推断总体的规律。\n",
    "\n",
    "**一个经典的类比**：假设我们想知道一个赌场里所有**同款老虎机**的平均中奖概率。我们有两种方法：\n",
    "1.  **空间平均 (Ensemble Average)**：在某个瞬间，把赌场里1000台老虎机全部玩一遍，然后计算这1000次结果的平均值。\n",
    "2.  **时间平均 (Time Average)**：只选择**其中一台**老虎机，连续不断地玩1000次，然后计算这1000次结果的平均值。\n",
    "\n",
    "如果这两种方法计算出的平均中奖概率是相等的，那么我们就说这个系统（所有老虎机的集合）具有**遍历性**。\n",
    "\n",
    "在金融领域，我们面对的现实是：我们永远无法进行“空间平均”。我们观察不到S&P 500指数在“平行宇宙”中的其他可能路径。我们拥有的，仅仅是它从诞生至今的**一条**历史路径数据。遍历性假设允许我们相信，通过分析这一条足够长的时间序列（时间平均），我们就可以推断出这个指数背后数据生成过程的真实统计特性（空间平均）。\n",
    "\n",
    "简单来说，**平稳性是遍历性的前提条件**。一个过程如果连自身的统计特性都在随时间变化（非平稳），那么我们观察的任何一段历史都不能代表它的“全部”，时间平均也就无从谈起了。\n",
    "\n",
    "### 为什么平稳性在金融时间序列中如此重要？\n",
    "\n",
    "平稳性是金融时间序列分析的基石，重要性体现在以下几个方面：\n",
    "\n",
    "#### 1. 它是模型有效性的前提\n",
    "许多经典的计量经济学模型，比如自回归模型（AR）、移动平均模型（MA）以及ARMA模型，都要求输入的数据是平稳的。这些模型的核心思想是，利用序列过去的行为和误差项来预测未来。如果序列的均值和方差等统计特性一直在变，那么基于历史数据估计出的模型参数就会不稳定，甚至毫无意义，无法用于未来的预测。\n",
    "\n",
    "#### 2. 它是有效预测的基础\n",
    "我们的目标是预测未来。如果一个时间序列是非平稳的，意味着它的行为模式在不断改变。比如一个公司的销售额，如果存在持续的增长趋势（均值不断变大），那么用过去十年的平均销售额来预测下个月的销售额，显然是荒谬的。只有当序列平稳时，我们才能假设“历史会在一定程度上重演”，过去的统计规律（如均值、波动性）在未来依然适用，从而让我们的预测有据可依。\n",
    "\n",
    "#### 3. 它可以帮助我们避免“伪回归”（Spurious Regression）的陷阱\n",
    "这是金融实证研究中最著名、也最危险的陷阱之一，也是对本科生最直观的警示。\n",
    "\n",
    "**真实的金融事实说明**：\n",
    "想象一下，你收集了两个毫不相关的时间序列数据：1990年到2020年“美国的名义GDP”和“马来西亚的棕榈油产量”。这两个序列很可能都是非平稳的，因为它们都随着经济发展和技术进步表现出明显的上升趋势。\n",
    "\n",
    "如果你直接将这两个非平稳序列进行回归分析，比如 `GDP = a + b * PalmOil + e`，你很可能会得到一个**极其“漂亮”**的结果：\n",
    "*   **很高的R²值**（比如0.9以上），显示模型解释力超强。\n",
    "*   **非常显著的t统计量**，显示棕榈油产量对GDP有显著的解释能力。\n",
    "\n",
    "看到这样的结果，你可能会兴奋地得出结论：“马来西亚的棕榈油产量是驱动美国GDP增长的关键因素！” 这显然是荒谬的。这种看似显著的统计关系其实是虚假的，它仅仅是因为两个序列共享了相似的时间趋势（都在增长），而并非存在任何真实的经济联系。这就是“伪回归”。\n",
    "\n",
    "**如何解决？**\n",
    "这个问题的根源在于序列的非平稳性。在金融实践中，我们通常不会直接对股价或GDP这样的水平值（Level）建模。我们会先对其进行**差分（Differencing）**处理，将其转换为平稳序列。\n",
    "\n",
    "*   **股价 vs. 股票收益率**：股价（Price）是非平稳的，但它的对数差分，也就是我们常说的**对数收益率**（Log Return），通常是平稳的。股票收益率序列的均值会稳定地围绕一个小的正数波动，其方差也相对稳定。\n",
    "*   **GDP vs. GDP增长率**：GDP总量是非平稳的，但GDP的同比增长率或环比增长率通常是平稳的。\n",
    "\n",
    "通过对数据进行差分等变换，我们把非平稳的序列变成了平稳的序列。然后，我们再用平稳的收益率或增长率序列去构建模型和进行回归分析，这样得出的结论才是统计上可靠的，避免了伪回归的谬误。\n",
    "\n",
    "**总结一下**：\n",
    "你可以这样理解：平稳性就像是为我们的金融数据分析设定了“公平的赛道”。如果数据本身在随时间“变形”（非平稳），那么任何在历史赛道上总结出的规律都无法指导未来的比赛。我们必须通过差分等手段，将数据“拉直”到一条平稳的赛道上，然后才能运用各种强大的计量工具进行建模、预测和检验，得出有意义的结论。遍历性则为我们提供了理论上的信心，让我们相信在平稳的赛道上，跑得足够久，就能看清赛道本身的全貌。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0830977e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === 单元格 47: 导入依赖库、循环/迭代 ===\n",
    "from statsmodels.tsa.stattools import adfuller as ADF\n",
    "\n",
    "# 对月收益率数据进行ADF检验\n",
    "adf_result = ADF(Month_data['2000-01':'2024-09']['Ret'])\n",
    "\n",
    "print('原始序列的ADF检验结果:')\n",
    "print(f'ADF Statistic: {adf_result[0]:.4f}')\n",
    "print(f'p-value: {adf_result[1]:.4f}')\n",
    "print('Critical Values:')\n",
    "for key, value in adf_result[4].items():\n",
    "    print(f'   {key}: {value:.4f}')\n",
    "\n",
    "if adf_result[1] <= 0.05:\n",
    "    print('结论: p-value小于0.05，拒绝原假设，序列是平稳的。')\n",
    "else:\n",
    "    print('结论: p-value大于0.05，未能拒绝原假设，序列是非平稳的。')"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
